#include "ble.h"

BLE::BLE(QObject *parent) : QObject(parent)
{
    init();
}

BLE::~BLE()
{
    delete m_LowController;
    delete m_DiscoveryAgent;
    servicesList.clear();
    characterList.clear();
    bleDevicesList.clear();
}

void BLE::init()
{
    m_DiscoveryAgent = new QBluetoothDeviceDiscoveryAgent();    //蓝牙搜索类
    m_DiscoveryAgent->setLowEnergyDiscoveryTimeout(5000);
    connect(m_DiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,[=](const QBluetoothDeviceInfo &info){
        if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration){
            qDebug()<<info.name()<<info.address().toString();
            bleDevicesList.append(info);
        }
    });
//    connect(m_DiscoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),[=](QBluetoothDeviceDiscoveryAgent::Error error){
//        if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError){
//            qDebug("The Bluetooth is powered off.");
//        }
//        else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError) {
//            qDebug("Writing or reading from the device resulted in an error.");
//        }
//    });
    connect(m_DiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, [=]{
        if (bleDevicesList.isEmpty())
            qDebug("No Low Energy devices found...");
        else
            qDebug("Scan finished!");
        emit signal_scanFinished();
        isScanning = false;
    });
}

//开始扫描设备
void BLE::startScanDevices()
{
    //清空设备列表
    bleDevicesList.clear();
    //开始扫描
    if(m_LowController)
    {
         qDebug("state");
        m_LowController->disconnectFromDevice();
        m_LowController->state();
    }

    m_DiscoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
    if(m_DiscoveryAgent->isActive()){
        qDebug("Scanning.\n");
        isScanning = true;
    }
}

//连接设备
void BLE::connectDevice(QString address)
{
    for(auto dev : bleDevicesList){
        if(dev.address().toString() == address){
            nowDevice = dev;
        }
    }
    if(!nowDevice.isValid()){
        qDebug("Not a valid device");
        return;
    }

    servicesList.clear();
    characterList.clear();

    if (m_LowController && previousAddress != nowDevice.address().toString()) {
        m_LowController->disconnectFromDevice();
        delete m_LowController;
        m_LowController = nullptr;
        m_service = nullptr;
    }

    if (!m_LowController) {
        m_LowController = QLowEnergyController::createCentral(nowDevice);
        connect(m_LowController, &QLowEnergyController::connected,[=](){
            qDebug("Device connect success.");
            qDebug("state:%d\r\n",m_LowController->state());
            m_LowController->discoverServices();
        });
//        connect(m_LowController, QOverload<QLowEnergyController::Error>::of(&QLowEnergyController::error),[=](QLowEnergyController::Error){
//            qDebug()<<"Error : "+m_LowController->errorString();
//        });
        connect(m_LowController, &QLowEnergyController::disconnected,[=]{
            qDebug("Device disconnected.");
        });
        connect(m_LowController, &QLowEnergyController::serviceDiscovered,[=]{
            //
        });
        connect(m_LowController, &QLowEnergyController::discoveryFinished,[=]{
            qDebug("Services scan finished.");

            servicesUUIDList = m_LowController->services();
            for(auto s : servicesUUIDList){
                qDebug()<<s.toString();
            }
            emit signal_findservicesFinished();
        });
    }

    m_LowController->connectToDevice();
    previousAddress = nowDevice.address().toString();
}

void BLE::connectService(QString uuid)
{
   // QLowEnergyService *service = nullptr;
    m_service = nullptr;
    for(int i=0;i<servicesUUIDList.length();i++)
    {
        if(servicesUUIDList.at(i).toString() == uuid){
            m_service = m_LowController->createServiceObject(servicesUUIDList.at(i));
        }
    }

    if (!m_service)
        return;
    characterList.clear();


    if (m_service->state() == QLowEnergyService::DiscoveryRequired) {
        connect(m_service, &QLowEnergyService::stateChanged,this, &BLE::serviceDetailsDiscovered);
        m_service->discoverDetails();
        return;
    }
}


/*
"{0000ffe1-0000-1000-8000-00805f9b34fb}"
"{0000ffe2-0000-1000-8000-00805f9b34fb}"
*/

void BLE::senddata(const QByteArray &data)
{
    if(m_service == nullptr || m_LowController == nullptr)
      //  return;
    if(m_LowController->state()!=QLowEnergyController::DiscoveredState)
      // return;
 //   qDebug("send state:%d\r\n",m_LowController->state());
    characterList = m_service->characteristics();
    QLowEnergyCharacteristic ch = characterList.at(0);
    m_service->writeCharacteristic(ch,data);
    for (const QLowEnergyCharacteristic &ch : characterList) {

        if(ch.isValid()){
//            if(ch.properties() & QLowEnergyCharacteristic::Notify){
//                                QLowEnergyDescriptor notice = ch.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
//                                if(notice.isValid()){
//                                    service->writeDescriptor(notice,QByteArray::fromHex("0100"));
//                                }
//            }
             qDebug()<<"1 2 3";
            //01 03 00 01 00 09 D4 0C
//            if(ch.properties() & QLowEnergyCharacteristic::WriteNoResponse ||  ch.properties() & QLowEnergyCharacteristic::Write){
//                m_service->writeCharacteristic(ch,data);
//            }
            //            if(ch.properties() & QLowEnergyCharacteristic::Read){
            //                service->readCharacteristic(ch);
            //            }
        }
    }
}

void BLE::serviceDetailsDiscovered(QLowEnergyService::ServiceState newState)
{
    qDebug()<<"State : "<<newState;

    for(QLowEnergyCharacteristic ch : m_service->characteristics()){
        if (ch.uuid().toString().contains("6e400003")) {
             qDebug()<<"read characteristics:"<<ch.uuid().toString();
             //QLowEnergyDescriptor descriptor = ch.descriptor(s.uuid());
             QLowEnergyDescriptor descriptor = ch.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);

             // 启用通知的配置（这里使用 Notification，如果支持 Indication 可以使用 QLowEnergyDescriptor::WriteIndication）
             QByteArray configValue = QByteArray(2, 0x01); // 0x01 表示启用 Notification
             //descriptor.writeValue(configValue);
             descriptor.value();

             // 将描述符写入 BLE 设备
             //m_service->writeDescriptor(descriptor, QByteArray::fromHex("0100"));
             m_service->writeDescriptor(descriptor, QByteArray::fromHex("1"));
        }
    }
    if (newState != QLowEnergyService::ServiceDiscovered) {
//        if (newState != QLowEnergyService::DiscoveringServices) {

//        }
        return;
    }
    auto service = qobject_cast<QLowEnergyService *>(sender());
    if (!service){
        return;
    }

    //BLE设备特征值改变
    connect(service, &QLowEnergyService::characteristicChanged,[=](const QLowEnergyCharacteristic &c, const QByteArray &value){
        QString Charuuid = c.uuid().toString();
        QString Value = value.toHex();
        emit signal_bluetoothrevdata(value);
        qDebug()<<"BLE设备-"+Charuuid+"特性值发生变化："+ Value;
    });
    //当特征读取请求成功返回其值时，发出此信号。
    connect(service,&QLowEnergyService::characteristicRead,[=](const QLowEnergyCharacteristic &c, const QByteArray &value){
        QString Charname = c.uuid().toString();
        QString Value = value.toHex();
        qDebug()<<"BLE设备-"+Charname+"特性值读取到的值："+ Value;
    });
    //当特性值成功更改为newValue时，会发出此信号。
    connect(service,&QLowEnergyService::characteristicWritten,[=](const QLowEnergyCharacteristic &c, const QByteArray &value){
        QString Charname = c.uuid().toString();
        QString Value = value.toHex();
        qDebug()<<"BLE设备-"+Charname+"特性值成功写入值："+ Value;
    });
    //描述符修改
    connect(service,&QLowEnergyService::descriptorWritten,[=](const QLowEnergyDescriptor &descriptor, const QByteArray &newValue){
        QString Charname = QString("%1").arg(descriptor.name());
        qDebug()<<"BLE设备-"+Charname+"描述符成功写入值："+ QString(newValue);
    });
    //各种错误信息
//    connect(service, static_cast<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error),
//            [=](QLowEnergyService::ServiceError newErrorr)
//    {
//        if(QLowEnergyService::NoError == newErrorr){
//            qDebug()<<"没有发生错误。\n";
//        }
//        if(QLowEnergyService::OperationError==newErrorr){
//            qDebug()<<"错误: 当服务没有准备好时尝试进行操作!\n";
//        }
//        if(QLowEnergyService::CharacteristicReadError==newErrorr){
//            qDebug()<<"尝试读取特征值失败!\n";
//        }
//        if(QLowEnergyService::CharacteristicWriteError==newErrorr){
//            qDebug()<<"尝试为特性写入新值失败!\n";
//        }
//        if(QLowEnergyService::DescriptorReadError==newErrorr){
//            qDebug()<<"尝试读取描述符值失败!\n";
//        }
//        if(QLowEnergyService::DescriptorWriteError==newErrorr){
//            qDebug()<<"尝试向描述符写入新值失败!\n";
//        }
//        if(QLowEnergyService::UnknownError==newErrorr){
//            qDebug()<<"与服务交互时发生未知错误!\n";
//        }
//    });

    characterList = service->characteristics();
    emit signal_findcharsFinished();

    for(auto s : characterList){
        qDebug()<<s.uuid();
    }

//    for (const QLowEnergyCharacteristic &ch : characterList) {

//        if(ch.isValid()){
//            if(ch.properties() & QLowEnergyCharacteristic::Notify){
//                QLowEnergyDescriptor notice = ch.descriptor(QBluetoothUuid::DescriptorType::ClientCharacteristicConfiguration);
//                if(notice.isValid()){
//                    service->writeDescriptor(notice,QByteArray::fromHex("0100"));
//                }
//            }
//            //01 03 00 01 00 09 D4 0C
//            if(ch.properties() & QLowEnergyCharacteristic::WriteNoResponse ||  ch.properties() & QLowEnergyCharacteristic::Write){
//                QByteArray arr;
////                arr.resize(20);
////                for(int i=0;i<20;i++){
////                    arr[i] = static_cast<char>(i);
////                }
//                arr.resize(8);
//                arr[0] = 0x01;
//                arr[1] = 0x03;
//                arr[2] = 0x00;
//                arr[3] = 0x01;
//                arr[4] = 0x00;
//                arr[5] = 0x09;
//                arr[6] = 0xD4;
//                arr[7] = 0x0C;
//                service->writeCharacteristic(ch,arr);
//            }
////            if(ch.properties() & QLowEnergyCharacteristic::Read){
////                service->readCharacteristic(ch);
////            }
//        }
//    }
}
